·#include "voice.h"
#include "ui_voice.h"
#include "photo.h"
#include "light.h"
#include "beep.h"
#include "camera.h" // 添加相机头文件
#include "beep.h"  // 添加报警头文件
#include <sys/stat.h>
#include <unistd.h> // for lseek, read, close
#include <cstring>  // for memset
#include <cstdio>   // for perror
#include <sys/socket.h> // for socket functions
#include <netinet/in.h> // for sockaddr_in
#include <arpa/inet.h>  // for inet_addr
voice::voice(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::voice)
{
    ui->setupUi(this);
    ui->pushButton->setStyleSheet("border-image: url(./btn1.jpg);");
    ui->pushButton_2->setStyleSheet("border-image: url(./btn1.jpg);");

    QPalette pal = this->palette();
    pal.setBrush(QPalette::Background,QBrush(QPixmap("./bg.jpg")));
    setPalette(pal);
    // 初始化变量
    sock_fd = -1;
    fd = -1;
    ret = -1;
}

voice::~voice()
{
    delete ui;

    // 关闭所有打开的文件描述符
    if (fd >= 0) ::close(fd);
    if (sock_fd >= 0) ::close(sock_fd);
}

// 返回主界面
void voice::on_pushButton_clicked()
{
    if (QWidget *parent = this->parentWidget()) {
        parent->show();
        parent->raise();
    }
    this->close();
}

// 语音识别功能
// 语音识别功能
void voice::on_pushButton_2_clicked()
{
    // 设置初始状态
    ui->label->setText("开始录音...");
    qApp->processEvents();

    qDebug() << "开始录音";
    ui->label->setText("正在录音(5秒)...");
    qApp->processEvents();

    // 执行录音命令（5秒录制）
    int recordStatus = system("arecord -d5 -c1 -r16000 -fS16_LE 1.wav >/dev/null 2>&1");
    if (recordStatus != 0) {
        qDebug() << "录音失败";
        ui->label->setText("录音失败，请检查麦克风!");
        return;
    }

    ui->label->setText("录音完成，正在连接服务器...");
    qApp->processEvents();

    // 创建套接字
    sock_fd = socket(PF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        qDebug() << "套接字创建失败";
        ui->label->setText("网络连接失败!");
        QMessageBox::critical(this, "错误", "网络连接失败");
        return;
    }

    // 设置服务器地址
    struct sockaddr_in srvaddr;
    memset(&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(55555);
    srvaddr.sin_addr.s_addr = inet_addr("192.168.2.194");

    // 设置超时选项
    struct timeval timeout;
    timeout.tv_sec = 10; // 10秒超时
    timeout.tv_usec = 0;
    setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
    setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

    // 发起连接请求
    ui->label->setText("正在连接语音识别服务器...");
    qApp->processEvents();

    if (::connect(sock_fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) < 0) {
        qDebug() << "服务器连接失败";
        ui->label->setText("服务器连接失败!");
        QMessageBox::critical(this, "错误", "服务器连接失败");
        ::close(sock_fd);
        return;
    }

    ui->label->setText("服务器连接成功!");
    qApp->processEvents();

    // 打开录音文件
    ui->label->setText("打开录音文件...");
    qApp->processEvents();

    int fd = open("1.wav", O_RDONLY);
    if (fd < 0) {
        qDebug() << "文件打开失败";
        ui->label->setText("无法打开录音文件!");
        QMessageBox::critical(this, "错误", "无法打开录音文件");
        ::close(sock_fd);
        return;
    }

    // 获取文件大小
    long file_size;
    lseek(fd, 0, SEEK_END);
    file_size = lseek(fd, 0, SEEK_CUR);
    lseek(fd, 0, SEEK_SET);
    qDebug() << "文件大小:" << file_size;

    // 发送文件大小
    ui->label->setText("发送音频文件信息...");
    qApp->processEvents();
    send(sock_fd, &file_size, sizeof(long), 0);

    ui->label->setText(QString("发送音频数据(%1 KB)...").arg(file_size/1024));
    qApp->processEvents();

    // 分段发送文件内容
    char buf[1024];
    ssize_t bytes_read;
    long total_sent = 0;
    while (1) {
        bytes_read = read(fd, buf, sizeof(buf));
        if (bytes_read <= 0) break;  // 文件结束或错误

        ssize_t bytes_sent = send(sock_fd, buf, bytes_read, 0);
        if (bytes_sent < 0) {
            perror("发送文件失败");
            ui->label->setText("发送音频数据失败!");
            break;
        }

        total_sent += bytes_sent;
        // 更新发送进度
        if (total_sent % (50 * 1024) < 1024) { // 每50KB更新一次
            int progress = (total_sent * 100) / file_size;
            ui->label->setText(QString("发送进度: %1% (%2 KB/%3 KB)")
                               .arg(progress)
                               .arg(total_sent/1024)
                               .arg(file_size/1024));
            qApp->processEvents();
        }
    }

    ::close(fd);
    qDebug() << "文件发送完成";
    ui->label->setText("音频发送完成，等待识别结果...");
    qApp->processEvents();

    // 接收服务器响应
    const int BUF_SIZE = 4096;
    char* response = new char[BUF_SIZE]();
    memset(response, 0, BUF_SIZE);

    ui->label->setText("正在接收识别结果...");
    qApp->processEvents();

    // 分段接收数据，确保完整接收
    ssize_t total_received = 0;
    ssize_t bytes_received = 0;
    while (total_received < BUF_SIZE - 1) {
        bytes_received = recv(sock_fd, response + total_received,
                             BUF_SIZE - total_received - 1, 0);

        if (bytes_received <= 0) {
            break;  // 连接关闭或出错
        }

        total_received += bytes_received;

        // 检查是否接收完XML结束标签
        if (strstr(response, "</nlp>") != nullptr) {
            break;  // 已接收完整XML响应
        }
    }

    if (total_received <= 0) {
        qDebug() << "未收到服务器响应";
        ui->label->setText("未收到识别结果!");
        QMessageBox::information(this, "错误", "未收到服务器响应");
    } else {
        // 确保字符串终止
        response[total_received] = '\0';

        qDebug() << "原始服务器响应:\n" << response;

        // 提取<rawtext>标签内容
        QString result;
        char* start_tag = strstr(response, "<rawtext>");
        char* end_tag = strstr(response, "</rawtext>");

        if (start_tag && end_tag && end_tag > start_tag) {
            // 计算文本内容位置
            start_tag += strlen("<rawtext>");  // 移动到文本开头
            size_t text_len = end_tag - start_tag;
            char rawtext[256] = {0};
            strncpy(rawtext, start_tag, text_len);
            result = QString::fromUtf8(rawtext);
        } else {
            result = QString::fromUtf8(response);
        }

        qDebug() << "提取的识别文本:" << result;
        ui->label->setText("识别结果: " + result);
        qApp->processEvents();

        // 处理识别结果 - 添加"图库"作为"相册"的同义词
        if (result.contains("图库") || result.contains("相册")) {
            ui->label->setText("执行命令: 打开相册");
            photo *album = new photo(this);
            album->setAttribute(Qt::WA_DeleteOnClose);
            album->show();
            this->hide();
        }
        else if (result.contains("报警")) {
            ui->label->setText("执行命令: 打开报警");
            beep *b = new beep(this);
            b->setAttribute(Qt::WA_DeleteOnClose);
            b->show();
            this->hide();
        }
        else if (result.contains("警报")) {
            ui->label->setText("执行命令: 打开警报");
            beep *b = new beep(this);
            b->setAttribute(Qt::WA_DeleteOnClose);
            b->show();
            this->hide();
        }
        else if (result.contains("相机")) {
            ui->label->setText("执行命令: 打开相机");
            camera *c = new camera(this);
            c->setAttribute(Qt::WA_DeleteOnClose);
            c->show();
            this->hide();
        }
        else if (result.contains("灯")) {
            ui->label->setText("执行命令: 打开灯光");
            light *l = new light(this);
            l->setAttribute(Qt::WA_DeleteOnClose);
            l->show();
            this->hide();
        }
        else if (result.contains("没有识别结果")) {
            ui->label->setText("未识别到有效指令");
            QMessageBox::information(this, "提示", "未识别到有效指令");
        }
        else {
            ui->label->setText("未知指令: " + result);
            QMessageBox::information(this, "提示", "未知指令");
        }
    }

    // 清理内存
    delete[] response;

    // 关闭套接字
    ::close(sock_fd);
    sock_fd = -1;

    // 恢复按钮状态
    ui->label->setText("语音识别完成");
    qApp->processEvents();
}
